
/*
 * Copyright 2002-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2018原创作者。
 *
 *根据Apache许可证2.0版许可（“许可证”）；
 *除非符合许可证的规定，否则您不得使用此文件。
 *您可以在以下网址获取许可证副本：
 *
 *https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，软件
 *根据许可证进行的分发是在“按原样”的基础上进行的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限的特定语言，请参阅许可证和
 *许可证下的限制。
 */

package org.springframework.scheduling.concurrent;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.lang.Nullable;

/**
 * A Spring {@link FactoryBean} that builds and exposes a preconfigured {@link ForkJoinPool}.
 *
 * @author Juergen Hoeller
 * @since 3.1
 */
/**
 *一个Spring｛@link FactoryBean｝，它构建并公开预配置的｛@linkForkJoinPool｝。
 *
 *@作者于尔根·霍勒
 *@自3.1起
 */
public class ForkJoinPoolFactoryBean implements FactoryBean<ForkJoinPool>, InitializingBean, DisposableBean {

	private boolean commonPool = false;

	private int parallelism = Runtime.getRuntime().availableProcessors();

	private ForkJoinPool.ForkJoinWorkerThreadFactory threadFactory = ForkJoinPool.defaultForkJoinWorkerThreadFactory;

	@Nullable
	private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;

	private boolean asyncMode = false;

	private int awaitTerminationSeconds = 0;

	@Nullable
	private ForkJoinPool forkJoinPool;


	/**
	 * Set whether to expose JDK 8's 'common' {@link ForkJoinPool}.
	 * <p>Default is "false", creating a local {@link ForkJoinPool} instance based on the
	 * {@link #setParallelism "parallelism"}, {@link #setThreadFactory "threadFactory"},
	 * {@link #setUncaughtExceptionHandler "uncaughtExceptionHandler"} and
	 * {@link #setAsyncMode "asyncMode"} properties on this FactoryBean.
	 * <p><b>NOTE:</b> Setting this flag to "true" effectively ignores all other
	 * properties on this FactoryBean, reusing the shared common JDK {@link ForkJoinPool}
	 * instead. This is a fine choice on JDK 8 but does remove the application's ability
	 * to customize ForkJoinPool behavior, in particular the use of custom threads.
	 * @since 3.2
	 * @see java.util.concurrent.ForkJoinPool#commonPool()
	 */
	/**
	 *设置是否公开JDK 8的“common”｛@link ForkJoinPool｝。
	 *＜p＞默认值为“false”，基于
	 *｛@link#setParallelism“parallelism”｝、｛@link#setThreadFactory“threadFactory”｝，
	 *｛@link#setUnaughtExceptionHandler“uncaughtExcessionHandler”｝和
	 *｛@link#setAsyncMode“asyncMode”｝属性。
	 *<p><b>注意：</b>将此标志设置为“true”实际上会忽略所有其他标志
	 *属性，重用共享的公共JDK｛@link ForkJoinPool｝
	 *相反。这是JDK8上的一个不错的选择，但确实会删除应用程序的功能
	 *自定义ForkJoinPool行为，特别是使用自定义线程。
	 *@自3.2起
	 *@参见java.util.concurrent.FukJoinPool#commonPool（）
	 */
	public void setCommonPool(boolean commonPool) {
		this.commonPool = commonPool;
	}

	/**
	 * Specify the parallelism level. Default is {@link Runtime#availableProcessors()}.
	 */
	/**
	 *指定并行度级别。默认值为｛@link Runtime#available Processors（）｝。
	 */
	public void setParallelism(int parallelism) {
		this.parallelism = parallelism;
	}

	/**
	 * Set the factory for creating new ForkJoinWorkerThreads.
	 * Default is {@link ForkJoinPool#defaultForkJoinWorkerThreadFactory}.
	 */
	/**
	 *设置用于创建新ForkJoinWorkerThreads的工厂。
	 *默认为｛@link ForkJoinPool#defaultForkJoinWorkerThreadFactory｝。
	 */
	public void setThreadFactory(ForkJoinPool.ForkJoinWorkerThreadFactory threadFactory) {
		this.threadFactory = threadFactory;
	}

	/**
	 * Set the handler for internal worker threads that terminate due to unrecoverable errors
	 * encountered while executing tasks. Default is none.
	 */
	/**
	 *为由于不可恢复的错误而终止的内部工作线程设置处理程序
	 *执行任务时遇到。默认值为“无”。
	 */
	public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
		this.uncaughtExceptionHandler = uncaughtExceptionHandler;
	}

	/**
	 * Specify whether to establish a local first-in-first-out scheduling mode for forked tasks
	 * that are never joined. This mode (asyncMode = {@code true}) may be more appropriate
	 * than the default locally stack-based mode in applications in which worker threads only
	 * process event-style asynchronous tasks. Default is {@code false}.
	 */
	/**
	 *指定是否为分支任务建立本地先进先出调度模式
	 *从未加入的。这种模式（asyncMode＝｛@code true｝）可能更合适
	 *而不是仅工作线程的应用程序中默认的基于本地堆栈的模式
	 *处理事件式异步任务。默认值为｛@code false｝。
	 */
	public void setAsyncMode(boolean asyncMode) {
		this.asyncMode = asyncMode;
	}

	/**
	 * Set the maximum number of seconds that this ForkJoinPool is supposed to block
	 * on shutdown in order to wait for remaining tasks to complete their execution
	 * before the rest of the container continues to shut down. This is particularly
	 * useful if your remaining tasks are likely to need access to other resources
	 * that are also managed by the container.
	 * <p>By default, this ForkJoinPool won't wait for the termination of tasks at all.
	 * It will continue to fully execute all ongoing tasks as well as all remaining
	 * tasks in the queue, in parallel to the rest of the container shutting down.
	 * In contrast, if you specify an await-termination period using this property,
	 * this executor will wait for the given time (max) for the termination of tasks.
	 * <p>Note that this feature works for the {@link #setCommonPool "commonPool"}
	 * mode as well. The underlying ForkJoinPool won't actually terminate in that
	 * case but will wait for all tasks to terminate.
	 * @see java.util.concurrent.ForkJoinPool#shutdown()
	 * @see java.util.concurrent.ForkJoinPool#awaitTermination
	 */
	/**
	 *设置此ForkJoinPool应该阻止的最大秒数
	 *以等待剩余任务完成执行
	 *在容器的其余部分继续关闭之前。尤其是
	 *如果您的剩余任务可能需要访问其他资源，则非常有用
	 *它们也由容器管理。
	 *<p>默认情况下，此ForkJoinPool根本不会等待任务的终止。
	 *它将继续全面执行所有正在进行的任务以及所有剩余任务
	 *队列中的任务，同时关闭容器的其余部分。
	 *相反，如果使用此属性指定等待终止期，
	 *该执行器将等待给定的时间（max）来终止任务。
	 *<p>请注意，此功能适用于｛@link#setCommonPool“commonPool”｝
	 *模式。基础ForkJoinPool实际上不会终止于
	 *case，但将等待所有任务终止。
	 *@参见java.util.concurrent.FukJoinPool#关闭（）
	 *@参见java.util.concurrent.FukJoinPool#awaitTermination
	 */
	public void setAwaitTerminationSeconds(int awaitTerminationSeconds) {
		this.awaitTerminationSeconds = awaitTerminationSeconds;
	}

	@Override
	public void afterPropertiesSet() {
		this.forkJoinPool = (this.commonPool ? ForkJoinPool.commonPool() :
				new ForkJoinPool(this.parallelism, this.threadFactory, this.uncaughtExceptionHandler, this.asyncMode));
	}


	@Override
	@Nullable
	public ForkJoinPool getObject() {
		return this.forkJoinPool;
	}

	@Override
	public Class<?> getObjectType() {
		return ForkJoinPool.class;
	}

	@Override
	public boolean isSingleton() {
		return true;
	}


	@Override
	public void destroy() {
		if (this.forkJoinPool != null) {
			// Ignored for the common pool.
			// 对于公用池已忽略。
			this.forkJoinPool.shutdown();

			// Wait for all tasks to terminate - works for the common pool as well.
			// 等待所有任务终止-也适用于公共池。
			if (this.awaitTerminationSeconds > 0) {
				try {
					this.forkJoinPool.awaitTermination(this.awaitTerminationSeconds, TimeUnit.SECONDS);
				}
				catch (InterruptedException ex) {
					Thread.currentThread().interrupt();
				}
			}
		}
	}

}
